home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / lists / mint / l_1599 / 1554 < prev    next >
Encoding:
Internet Message Format  |  1994-08-27  |  30.8 KB

  1. Subject: Re: MiNT 1.10 re-sync
  2. Date: Thu, 9 Jun 94 20:35:06 CDT
  3. From: Juergen Lock <nox@jelal.north.de>
  4. In-Reply-To: <9406080703.AA15701@hera.rbi.informatik.uni-frankfurt.de>; from "Kay Roemer" at Jun 8, 94 9:03 am
  5. Message-Id: <9406091835.AA00187@jelal.north.de>
  6.  
  7. Kay Roemer writes:
  8.  
  9. > > Upon reflection, it would probably be easier to load shared text regions at the
  10. > > top of memory, and continue creating the TPA from lower memory. That way you
  11. > > don't have to worry about artificially limiting the amount of memory you give
  12. > > to a newly spawned process. (I wonder how topdown solved this problem...)
  13. > This sounds like a possible solution.
  14.  
  15.  hmm i don't know, doesn't falcons need free space at top when changing
  16. screen size (s_realloc)?
  17.  
  18. >  TPA doesn't matter in this case, because
  19. > it is freed when the process (running a shared text) exits. Fragmentation seems
  20. > to occur, when
  21. > 1) running shared text
  22. > 2) last process running shared text exits, shared text still hangs around.
  23. > 3) allocating memory in eg, a device driver or fs or running TSR or daemon.
  24.  
  25.  and when MiNT needs a new nalloc arena...
  26.  
  27. > 4) goto 1
  28. > After a few iterations the stuff allocated in 3) prevents the free shared
  29. > text regions from beeing joined together to one large hunk.
  30. > Sigh! Thats a real problem when physical address space == virtual address
  31. > space.
  32.  
  33.  yes :-(
  34. > Kay.
  35.  
  36.  ok here is what i've been testing the last few weeks.  works for me
  37. although there could still be bugs that only show up on 68030, etc.
  38. but first a few other fixes to add to Michaels collection. :)
  39.  
  40. 0. this was missing:  use new value for TIOCSETP and keep old for
  41. TIOCSETN, other way around can hang old binaries...
  42.  
  43. Index: file.h
  44. @@ -340,7 +341,7 @@
  45.  #define FIONREAD    (('F'<< 8) | 1)
  46.  #define FIONWRITE    (('F'<< 8) | 2)
  47.  #define TIOCGETP    (('T'<< 8) | 0)
  48. -#define TIOCSETP    (('T'<< 8) | 1)
  49. +#define TIOCSETN    (('T'<< 8) | 1)
  50.  #define TIOCGETC    (('T'<< 8) | 2)
  51.  #define TIOCSETC    (('T'<< 8) | 3)
  52.  #define TIOCGLTC    (('T'<< 8) | 4)
  53. @@ -361,7 +362,7 @@
  54.  #define TIOCGFLAGS    (('T'<< 8) | 22)
  55.  #define TIOCSFLAGS    (('T'<< 8) | 23)
  56.  #define TIOCOUTQ    (('T'<< 8) | 24)
  57. -#define TIOCSETN    (('T'<< 8) | 25)
  58. +#define TIOCSETP    (('T'<< 8) | 25)
  59.  
  60.  /* cursor control Fcntls:
  61.   * NOTE THAT THESE MUST BE TOGETHER
  62.  
  63. 1. getcwd crashed when called from `unmounted' (Dlock) fs...
  64.  
  65. Index: unifs.c
  66. @@ -379,6 +379,10 @@
  67.          return EINTRN;
  68.      }
  69.  
  70. +    if (!fs) {
  71. +        *pathname = 0;
  72. +        return 0;
  73. +    }
  74.      if (!(fs->fsflags & FS_LONGPATH)) {
  75.          r = (*fs->getname)(&curproc->root[dir->dev], dir, tmppath, PATH_MAX);
  76.          if (r) return r;
  77.  
  78. 2. ls -l /pipe: fix pty modes (S_IFCHR) and 14-char names
  79.  
  80. Index: pipefs.c
  81. @@ -477,11 +477,12 @@
  82.          outp->readers = 1; outp->writers = selfread ? 1 : VIRGIN_PIPE;
  83.          outp->wsel = outp->rsel = 0;
  84.      }
  85. +    b->name[NAME_MAX] = '\0';
  86.      strncpy(b->name, name, NAME_MAX);
  87.      b->time = timestamp;
  88.      b->date = datestamp;
  89.      b->dosflags = attrib;
  90. -    b->mode = ((attrib & FA_SYSTEM) ? S_IFCHR : S_IFIFO) | mode;
  91. +    b->mode = ((attrib & FA_SYSTEM) ? S_IFCHR : S_IFIFO) | (mode & ~S_IFMT);
  92.      b->uid = curproc->ruid;
  93.      b->gid = curproc->rgid;
  94.  
  95. 3. make echo >pipe/pty work when other end already open, only fail if
  96. O_EXCL or Fcreate attr != 0. (shells often creat() output redirection...)
  97.  
  98. Index: dosfile.c
  99. @@ -34,7 +35,7 @@
  100.      unsigned perm;
  101.      int creating;
  102.      char temp1[PATH_MAX];
  103. -    extern FILESYS proc_filesys;
  104. +    extern FILESYS proc_filesys, pipe_filesys;
  105.  
  106.  /* for special BIOS "fake" devices */
  107.      extern DEVDRV fakedev;
  108. @@ -59,9 +60,12 @@
  109.  
  110.  /*
  111.   * file found: this is an error if (O_CREAT|O_EXCL) are set
  112. + *    ...or if this is Fcreate with nonzero attr on the pipe filesystem
  113.   */
  114.  
  115. -    if ( (r == 0) && ( (rwmode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) ) ) {
  116. +    if ( (r == 0) && ( (rwmode & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL) ||
  117. +            (attr && fc.fs == &pipe_filesys &&
  118. +            (rwmode & (O_CREAT|O_TRUNC)) == (O_CREAT|O_TRUNC)))) {
  119.          DEBUG(("do_open(%s): file already exists",name));
  120.          mint_errno = EACCDN;
  121.          release_cookie(&fc);
  122. Index: pipefs.c
  123. @@ -544,10 +545,12 @@
  124.          }
  125.          p->flags &= ~O_HEAD;
  126.      } else {
  127. +#if 0
  128.          if (f->flags & O_TRUNC) {
  129.              DEBUG(("pipe_open: fifo already exists"));
  130.              return EACCDN;
  131.          }
  132. +#endif
  133.      }
  134.  /*
  135.   * check for file sharing compatibility. note that O_COMPAT gets mutated
  136.  
  137. 4. save a long read
  138.  
  139. Index: intr.spp
  140. @@ -42,7 +42,7 @@
  141.  _mint_5ms:
  142.      move.l    a0,-(sp)
  143.      lea    _uptimetick,a0
  144. -    tst.l    _uptimetick
  145. +    tst.l    (a0)
  146.      bne.s    L_no_uptime
  147.      move.l    #200,(a0)
  148.  L_no_uptime:
  149.  
  150. 5. fork() doesn't copy shared text regions so why allocate memory
  151. to save them :)
  152.  
  153. Index: dosmem.c
  154. @@ -1283,6 +1294,15 @@
  155.      if (save) {
  156.          TRACE(("do_vfork: saving parent"));
  157.          savesize = memused(curproc) - txtsize;
  158. +        if (!txtsize && (p->base->p_flags & F_SHTEXT)) {
  159. +            for (i = 0; i < curproc->num_reg; i++) {
  160. +                m = curproc->mem[i];
  161. +                if (m && (m->mflags & M_SHTEXT)) {
  162. +                    savesize -= m->len;
  163. +                    break;
  164. +                }
  165. +            }
  166. +        }
  167.          assert(savesize >= 0);
  168.  
  169.          saveplace = (char *)alloc_region(alt, savesize, PROT_P);
  170.  
  171. 6. and now the sticky text/fragmentation megapatch...  does a few things:
  172.  
  173. . if F_ALTLOAD|F_SHTEXT look at F_MINALT bits to see how much memory
  174. the new process needs and free sticky text regions if necessary, all
  175. F_MINALT bits set (0xf0000000) means `as much as you can get'
  176. . execv..() frees the old process memory before allocating the new ones,
  177. and so no longer leaves holes in your memory map.  this took a few
  178. ugly hacks but i think its worth it :)  the only visible change should
  179. be when exec'ing a damaged binary the process gets killed, fixing that
  180. would require reading executables twice.
  181. . check the sticky bit, just making everything sharable sticky still got
  182. me too much `out of memory's...  and free sticky text regions after disk
  183. changes or if open() would otherwise fail.
  184. . also free no more sticky text regions then necessary in alloc, and
  185. some other small changes.
  186.  
  187.  oh and if you need something to adjust the F_MINALT bits...
  188.  
  189. #! /usr/bin/perl
  190. # xsetf [-xhex] files ... -- print/set executable flags
  191. #
  192. $aexec = 's L L L L L L S';
  193. #     short    a_magic;    /* magic number */
  194. #unsigned long    a_text;        /* size of text segment */
  195. #unsigned long    a_data;        /* size of initialized data */
  196. #unsigned long    a_bss;        /* size of uninitialized data */
  197. #unsigned long    a_syms;        /* size of symbol table */
  198. #unsigned long    a_AZero1;    /* always zero */
  199. #unsigned long    a_ldflgs;    /* program load flags */
  200. #unsigned short    a_isreloc;    /* is reloc info present */
  201.  
  202. while ($_ = $ARGV[0], /^-/) {
  203.     shift;
  204.     last if /^--$/;
  205.     if (/^-x(.*)/) {
  206.         if ($1) {
  207.             $x = $1;
  208.         } else {
  209.             $x = shift;
  210.             next;
  211.         }
  212.     }
  213. }
  214. foreach (@ARGV) {
  215.     print $_, ":\t";
  216.     open (F, "+< $_") || die "Can't open";
  217.     sysread (F, $head, length (pack ($aexec, 0))) || die "Can't read header";
  218.     ($a_magic, $a_text, $a_data, $a_bss, $a_syms,
  219.         $a_AZero1, $a_ldflgs, $a_isreloc) = unpack ($aexec, $head);
  220.     die "not executable/corrupted header" unless $a_magic == 0x601a;
  221.     seek (F, 0, 0) || die "Can't seek back";
  222.     print "\n text ", $a_text, " data ", $a_data, " bss ", $a_bss, " symbols ",
  223.             $a_syms, " zero1 ", $a_AZero1, " isreloc ", $a_isreloc, "\n";
  224.     printf "\tldflags\t\t0x%08lx\n", $a_ldflgs;
  225.  
  226.     printf "\t &fload\t\t0x%08lx\n", 1    if ($a_ldflgs&1);
  227.     printf "\t &altload\t0x%08lx\n", 2    if ($a_ldflgs&2);
  228.     printf "\t &altalloc\t0x%08lx\n",4    if ($a_ldflgs&4);
  229.     printf "\t &prot_p\t0x%08lx = 0x%08lx\n",    0xf0,  0
  230.                         if (!($a_ldflgs&0xf0));
  231.     printf "\t &prot_g\t0x%08lx = 0x%08lx\n",    0xf0,  0x10
  232.                         if (($a_ldflgs&0xf0) == 0x10);
  233.     printf "\t &prot_s\t0x%08lx = 0x%08lx\n",    0xf0,  0x20
  234.                         if (($a_ldflgs&0xf0) == 0x20);
  235.     printf "\t &prot_pr\t0x%08lx = 0x%08lx\n",    0xf0,  0x30
  236.                         if (($a_ldflgs&0xf0) == 0x30);
  237.     printf "\t &prot_i\t0x%08lx = 0x%08lx\n",    0xf0,  0x40
  238.                         if (($a_ldflgs&0xf0) == 0x40);
  239.     printf "\t &prot_??\t0x%08lx = 0x%08lx\n",    0xf0, $a_ldflgs&0xf0
  240.                         if (($a_ldflgs&0xf0) > 0x40);
  241.     printf "\t &shtext\t0x%08lx\n",  0x800 if ($a_ldflgs&0x800);
  242.     printf "\t &minalt\t0x%08lx = 0x%08lx\n",    0xf0000000,
  243.             $a_ldflgs&0xf0000000    if ($a_ldflgs&0xf0000802);
  244.     if (defined ($x)) {
  245.         $x = oct ($x) if $x =~ /^0/;
  246.         $a_ldflgs = $x;
  247.     }
  248.     $newhead = pack ($aexec, $a_magic, $a_text, $a_data, $a_bss, $a_syms,
  249.         $a_AZero1, $a_ldflgs, $a_isreloc);
  250.     if ($newhead ne $head) {
  251.         syswrite (F, $newhead, length ($newhead)) == length ($newhead)
  252.             || die "Can't write back header";
  253.     }
  254.     close F || die "Can't close";
  255. }
  256. -------cut----
  257.  
  258.  the sticky bit is of course chmod +t.  (if your /bin/sh still is on
  259. GEMDOS change it now... :)  and then see you no longer need _shell_p.)
  260.  
  261. Index: dosfile.c
  262. @@ -9,6 +9,7 @@
  263.  #include "mint.h"
  264.  
  265.  extern char vt52xkey[];
  266. +MEMREGION *tofreed;    /* to-be-freed shared text region (set in denyshare) */
  267.  
  268.  static long do_dup P_((int,int));
  269.  static void unselectme P_((PROC *));
  270. @@ -232,6 +236,12 @@
  271.          dispose_fileptr(f);
  272.          return NULL;
  273.      }
  274. +
  275. +    if (tofreed) {
  276. +        tofreed->links = 0;
  277. +        free_region(tofreed);
  278. +        tofreed = 0;
  279. +    }
  280.  
  281.  /* special code for opening a tty */
  282.      if (is_terminal(f)) {
  283. Index: dosmem.c
  284. @@ -53,7 +53,7 @@
  285.      long maxsize, mleft;
  286.  
  287.      if (size == -1L) {
  288. -        maxsize = max_rsize(map);
  289. +        maxsize = max_rsize(map, 0L);
  290.          if (curproc->maxmem) {
  291.              mleft = curproc->maxmem - memused(curproc);
  292.              if (maxsize > mleft)
  293. @@ -420,6 +420,33 @@
  294.          }
  295.      }
  296.  
  297. +/* make a local copy of the name, in case we are overlaying the current
  298. + * process
  299. + */
  300. +    if (mkname) {
  301. +        lastslash = 0;
  302. +        newname = ptr1;
  303. +        while (*newname) {
  304. +            if (*newname == '\\' || *newname == '/')
  305. +                lastslash = newname;
  306. +            ++newname;
  307. +        }
  308. +        if (!lastslash)
  309. +            lastslash = ptr1;
  310. +        else
  311. +            lastslash++;
  312. +
  313. +        i = 0; newname = localname;
  314. +        while (i++ < PNAMSIZ) {
  315. +            if (*lastslash == '.' || *lastslash == 0) {
  316. +                *newname = 0; break;
  317. +            }
  318. +            else
  319. +                *newname++ = *lastslash++;
  320. +        }
  321. +        *newname = 0;
  322. +    }
  323. +
  324.  TRACE(("creating environment"));
  325.  
  326.      if (mkload || mkbase) {
  327. @@ -434,7 +461,7 @@
  328.  TRACE(("creating base page"));
  329.  
  330.      if (mkbase) {
  331. -        base = create_base((char *)ptr2, env, flags, 0L);
  332. +        base = create_base((char *)ptr2, env, flags, 0L, 0L, 0L, 0L, 0L, 0L);
  333.          if (!base) {
  334.              DEBUG(("Pexec: unable to create basepage"));
  335.              detach_region(curproc, env);
  336. @@ -444,8 +471,19 @@
  337.  TRACELOW(("Pexec: basepage region(%lx) is %ld bytes at %lx", base, base->len, base->loc));
  338.      }
  339.      else if (mkload) {
  340. -        base = load_region((char *)ptr1, env, (char *)ptr2,
  341. -            &xattr, &text, &flags);
  342. +        char cbuf[128], *tail = ptr2;
  343. +        if (overlay) {
  344. +            static char fbuf[PATH_MAX];
  345. +            ptr1 = strncpy (fbuf, ptr1, PATH_MAX-2);
  346. +            tail = strncpy (cbuf, ptr2, 127);
  347. +        }
  348. +#if 0
  349. +        base = load_region((char *)ptr1, env, (char *)tail,
  350. +            &xattr, &text, &flags, 0);
  351. +#else
  352. +        base = load_region((char *)ptr1, env, (char *)tail,
  353. +            &xattr, &text, &flags, overlay);
  354. +#endif
  355.          if (!base) {
  356.              DEBUG(("Pexec: load_region failed"));
  357.              detach_region(curproc, env);
  358. @@ -480,33 +518,6 @@
  359.  #endif
  360.      }
  361.  
  362. -/* make a local copy of the name, in case we are overlaying the current
  363. - * process
  364. - */
  365. -    if (mkname) {
  366. -        lastslash = 0;
  367. -        newname = ptr1;
  368. -        while (*newname) {
  369. -            if (*newname == '\\' || *newname == '/')
  370. -                lastslash = newname;
  371. -            ++newname;
  372. -        }
  373. -        if (!lastslash)
  374. -            lastslash = ptr1;
  375. -        else
  376. -            lastslash++;
  377. -
  378. -        i = 0; newname = localname;
  379. -        while (i++ < PNAMSIZ) {
  380. -            if (*lastslash == '.' || *lastslash == 0) {
  381. -                *newname = 0; break;
  382. -            }
  383. -            else
  384. -                *newname++ = *lastslash++;
  385. -        }
  386. -        *newname = 0;
  387. -    }
  388. -
  389.      if (mkload || mkbase) {
  390.          /*
  391.           * Now that the file's loaded, flags is set to the prgflags
  392. @@ -846,7 +857,7 @@
  393.     memory runs low. Assume that we will never have 65535 processes
  394.     using a particular memory region. */
  395.                  if (m->links == 0) {
  396. -                    if (m->mflags & M_SHTEXT)
  397. +                    if (m->mflags & M_SHTEXT_T)
  398.                          m->links = 0xffff;
  399.                      else
  400.                          free_region(m);
  401. @@ -1307,9 +1327,10 @@
  402.          }
  403.          savemem = addr2mem((virtaddr)saveplace);
  404.          assert(savemem);
  405. +        savemem->mflags |= M_FSAVED;
  406.          for (i = 0; i < curproc->num_reg; i++) {
  407.              m = curproc->mem[i];
  408. -            if (m && m != savemem && !(m->mflags & M_SHTEXT)) {
  409. +            if (m && !(m->mflags & (M_FSAVED|M_SHTEXT))) {
  410.                  if (i != 1 || txtsize == 0) {
  411.                      quickmove(saveplace, (char *)m->loc, m->len);
  412.                      saveplace += m->len;
  413. @@ -1354,23 +1375,7 @@
  414.      TRACE(("do_vfork: parent waking up"));
  415.  
  416.      if (save) {
  417. -        TRACE(("do_vfork: parent restoring memory"));
  418. -        saveplace = (char *)savemem->loc;
  419. -        for (i = 0; i < curproc->num_reg; i++) {
  420. -            m = curproc->mem[i];
  421. -            if (m && (m != savemem) && !(m->mflags & M_SHTEXT)) {
  422. -                if (i != 1 || txtsize == 0) {
  423. -                    quickmove((char *)m->loc, saveplace, m->len);
  424. -                    saveplace += m->len;
  425. -                }
  426. -                else {
  427. -                    quickmove((char *)m->loc+txtsize, saveplace,
  428. -                    m->len - txtsize);
  429. -                    saveplace += m->len - txtsize;
  430. -                }
  431. -            }
  432. -        }
  433. -        detach_region(curproc, savemem);
  434. +        fork_restore(curproc, 0L);
  435.      }
  436.      curproc->sigmask = sigmask;
  437.  /* note that the PROC structure pointed to by p may be freed during
  438. @@ -1380,6 +1385,50 @@
  439.      check_sigs();    /* did we get any signals while sleeping? */
  440.      return newpid;
  441.  }
  442. +
  443. +/*
  444. + * fork_restore(p): restore process memory after a blocking fork
  445. + */
  446. +
  447. +void fork_restore(p, savemem)
  448. +PROC *p;
  449. +MEMREGION *savemem;
  450. +{
  451. +    MEMREGION *m;
  452. +    long txtsize = p->txtsize;
  453. +    char *saveplace;
  454. +    int i;
  455. +
  456. +    if (!savemem) {
  457. +        for (i = 0; i < p->num_reg; i++) {
  458. +            m = p->mem[i];
  459. +            if (m && (m->mflags & M_FSAVED)) {
  460. +                savemem = m;
  461. +                break;
  462. +            }
  463. +        }
  464. +        if (!savemem)
  465. +            return;
  466. +    }
  467. +    saveplace = (char *)savemem->loc;
  468. +
  469. +    TRACE(("do_vfork: parent restoring memory"));
  470. +    for (i = 0; i < p->num_reg; i++) {
  471. +        m = p->mem[i];
  472. +        if (m && !(m->mflags & (M_FSAVED|M_SHTEXT))) {
  473. +            if (i != 1 || txtsize == 0) {
  474. +                quickmove((char *)m->loc, saveplace, m->len);
  475. +                saveplace += m->len;
  476. +            }
  477. +            else {
  478. +                quickmove((char *)m->loc+txtsize, saveplace,
  479. +                m->len - txtsize);
  480. +                saveplace += m->len - txtsize;
  481. +            }
  482. +        }
  483. +    }
  484. +    detach_region(p, savemem);
  485. +}
  486.  
  487.  /*
  488.   * here are the interfaces that the user sees. Pvfork() doesn't save
  489. Index: filesys.c
  490. @@ -367,7 +367,7 @@
  491.      int i;
  492.      FILEPTR *f;
  493.      FILESYS *fs;
  494. -    SHTEXT *stext;
  495. +    SHTEXT *stext, **old;
  496.      extern SHTEXT *text_reg;    /* in mem.c */
  497.      DIR *dirh;
  498.      fcookie dir;
  499. @@ -461,13 +461,25 @@
  500.      }
  501.  
  502.  /* free any file descriptors associated with shared text regions */
  503. -    for (stext = text_reg; stext; stext = stext->next) {
  504. +    for (old = &text_reg; (stext = *old);) {
  505.          f = stext->f;
  506.          if (f->fc.dev == d) {
  507.              f->dev = NULL;
  508.              do_pclose(rootproc, f);
  509.              stext->f = 0;
  510. +/* free region if unattached */
  511. +            if (stext->text->links == 0xffff) {
  512. +                stext->text->links = 0;
  513. +                stext->text->mflags &= ~(M_SHTEXT|M_SHTEXT_T);
  514. +                free_region(stext->text);
  515. +                *old = stext->next;
  516. +                kfree(stext);
  517. +                continue;
  518. +            }
  519. +/* else clear `sticky bit' */
  520. +            stext->text->mflags &= ~M_SHTEXT_T;
  521.          }
  522. +        old = &stext->next;
  523.      }
  524.  }
  525.  
  526. @@ -979,6 +991,8 @@
  527.  {
  528.      int newrm, newsm;    /* new read and sharing mode */
  529.      int oldrm, oldsm;    /* read and sharing mode of already opened file */
  530. +    extern MEMREGION *tofreed;
  531. +    MEMREGION *m = tofreed;
  532.      int i;
  533.  
  534.      newrm = f->flags & O_RWMODE;
  535. @@ -999,6 +1013,12 @@
  536.          oldsm = list->flags & O_SHMODE;
  537.          if (oldsm == O_DENYW || oldsm == O_DENYRW) {
  538.               if (newrm != O_RDONLY) {
  539. +/* conflict because of unattached shared text region? */
  540. +                if (!m && (m = find_text_seg(list))) {
  541. +                    if (m->links == 0xffff)
  542. +                        continue;
  543. +                    m = 0;
  544. +                }
  545.                  DEBUG(("write access denied"));
  546.                  return 1;
  547.              }
  548. @@ -1040,6 +1060,9 @@
  549.              ;    /* everything is OK */
  550.          }
  551.      }
  552. +/* cannot close shared text regions file here... have open do it. */
  553. +    if (m)
  554. +        tofreed = m;
  555.      return 0;
  556.  }
  557.  
  558. Index: mem.c
  559. @@ -576,7 +576,7 @@
  560.      ulong size;
  561.      int mode;
  562.  {
  563. -    MEMREGION *m, *n, *s;
  564. +    MEMREGION *m, *n, *nlast, *nfirstp, *s;
  565.  
  566.      TRACELOW(("get_region(%s,%lx,%x)",
  567.          (map == ker ? "ker" : (map == core ? "core" : "alt")),
  568. @@ -601,10 +601,12 @@
  569.  /* We come back and try again if we found and freed any unattached shared
  570.   * text regions.
  571.   */
  572. +    nfirstp = NULL;
  573.  retry:
  574. -    s = NULL;
  575. -
  576.      n = *map;
  577. +retry2:
  578. +    s = nlast = NULL;
  579. +
  580.      while (n) {
  581.          if (ISFREE(n)) {
  582.              if (n->len == size) {
  583. @@ -628,10 +630,13 @@
  584.                      return 0;
  585.                  }
  586.              }
  587. +            nlast = n;
  588.  /* If this is an unattached shared text region, leave it as a last resort */
  589.          } else if (n->links == 0xffff && (n->mflags & M_SHTEXT)) {
  590. -            if (!s)
  591. +            if (!s) {
  592.                  s = n;
  593. +                nfirstp = nlast;
  594. +            }
  595.          }
  596.          n = n->next;
  597.      }
  598. @@ -639,11 +644,60 @@
  599.  /* Looks like we're out of free memory. Try freeing an unattached shared text
  600.   * region, and then try again to fill this request.
  601.   */
  602. +#if 1
  603. +    if (s && s->len < size) {
  604. +        long lastsize = 0, end = 0;
  605. +
  606. +        n = nlast = nfirstp;
  607. +        if (!n || n->next != s)
  608. +            n = s;
  609. +        for (; n; n = n->next) {
  610. +            if (ISFREE(n)) {
  611. +                if (end == n->loc) {
  612. +                    lastsize += n->len;
  613. +                } else {
  614. +                    s = NULL;
  615. +                    nfirstp = nlast;
  616. +                    lastsize = n->len;
  617. +                }
  618. +                nlast = n;
  619. +                end = n->loc + n->len;
  620. +                if (lastsize >= size) {
  621. +                    break;
  622. +                }
  623. +            } else if (n->links == 0xffff && (n->mflags & M_SHTEXT)) {
  624. +                if (end == n->loc) {
  625. +                    if (!s)
  626. +                        s = n;
  627. +                    lastsize += n->len;
  628. +                } else {
  629. +                    s = n;
  630. +                    nfirstp = nlast;
  631. +                    lastsize = n->len;
  632. +                }
  633. +                end = n->loc + n->len;
  634. +                if (lastsize >= size) {
  635. +                    break;
  636. +                }
  637. +            }
  638. +        }
  639. +        if (!n)
  640. +            s = NULL;
  641. +    }
  642. +    if (s) {
  643. +        s->links = 0;
  644. +        free_region(s);
  645. +        if (!(n = nfirstp))
  646. +            n = *map;
  647. +        goto retry2;
  648. +    }
  649. +#else
  650.      if (s) {
  651.          s->links = 0;
  652.          free_region(s);
  653.          goto retry;
  654.      }
  655. +#endif
  656.          
  657.      if (m)
  658.          dispose_region(m);
  659. @@ -836,6 +890,7 @@
  660.      return 0;
  661.  }
  662.  
  663. +#if 0
  664.  /*
  665.   * max_rsize(map): return the length of the biggest free region
  666.   * in the given memory map, or 0 if no regions remain.
  667. @@ -879,6 +934,84 @@
  668.      }
  669.      return size;
  670.  }
  671. +#else
  672. +/*
  673. + * max_rsize(map, needed): return the length of the biggest free region
  674. + * in the given memory map, or 0 if no regions remain.
  675. + * needed is minimun amount needed, if != 0 try to keep unattached
  676. + * shared text regions, else count them all as free.
  677. + */
  678. +
  679. +long
  680. +max_rsize(map, needed)
  681. +    MMAP map;
  682. +    long needed;
  683. +{
  684. +    MEMREGION *m;
  685. +    long size = 0, lastsize = 0, end = 0;
  686. +
  687. +    if (needed) {
  688. +        for (m = *map; m; m = m->next) {
  689. +            if (ISFREE(m) ||
  690. +                (m->links == 0xfffe && !(m->mflags & M_SHTEXT))) {
  691. +                if (end == m->loc) {
  692. +                    lastsize += m->len;
  693. +                } else {
  694. +                    lastsize = m->len;
  695. +                }
  696. +                end = m->loc + m->len;
  697. +                if (lastsize > size) {
  698. +                    size = lastsize;
  699. +                }
  700. +            }
  701. +        }
  702. +        if (size >= needed)
  703. +            return size;
  704. +
  705. +        lastsize = end = 0;
  706. +    }
  707. +    for (m = *map; m; m = m->next) {
  708. +        if (ISFREE(m) || m->links == 0xfffe ||
  709. +            (m->links == 0xffff && (m->mflags & M_SHTEXT))) {
  710. +            if (end == m->loc) {
  711. +                lastsize += m->len;
  712. +            } else {
  713. +                lastsize = m->len;
  714. +            }
  715. +            end = m->loc + m->len;
  716. +            if (lastsize > size) {
  717. +                if (needed && lastsize >= needed)
  718. +                    return lastsize;
  719. +                size = lastsize;
  720. +            }
  721. +        }
  722. +    }
  723. +    return size;
  724. +}
  725. +
  726. +/*
  727. + * tot_rsize(map, flag): if flag == 1, return the total number of bytes in
  728. + * the given memory map; if flag == 0, return only the number of free
  729. + * bytes
  730. + */
  731. +
  732. +long
  733. +tot_rsize(map, flag)
  734. +    MMAP map;
  735. +    int flag;
  736. +{
  737. +    MEMREGION *m;
  738. +    long size = 0;
  739. +
  740. +    for (m = *map; m; m = m->next) {
  741. +        if (flag || ISFREE(m) ||
  742. +            (m->links == 0xffff && (m->mflags & M_SHTEXT))) {
  743. +            size += m->len;
  744. +        }
  745. +    }
  746. +    return size;
  747. +}
  748. +#endif
  749.  
  750.  /*
  751.   * alloc_region(MMAP map, ulong size, int mode): allocate a new region and
  752. @@ -979,61 +1112,195 @@
  753.      return m;
  754.  }
  755.  
  756. +static void terminateme(code)
  757. +    int code;
  758. +{
  759. +    Pterm (code);
  760. +}
  761. +
  762.  MEMREGION *
  763. -create_base(cmd, env, flags, prgsize)
  764. +create_base(cmd, env, flags, prgsize, execproc, s, f, fh, xp)
  765.      const char *cmd;
  766.      MEMREGION *env;
  767.      ulong flags, prgsize;
  768. +    PROC *execproc;
  769. +    SHTEXT *s;
  770. +    FILEPTR *f;
  771. +    FILEHEAD *fh;
  772. +    XATTR *xp;
  773.  {
  774. -    long len, coresize, altsize;
  775. +    long len = 0, minalt = 0, coresize, altsize;
  776.      MMAP map;
  777. -    MEMREGION *m;
  778. +    MEMREGION *m, *savemem = 0;
  779.      BASEPAGE *b;
  780. +    PROC *parent = 0;    /* keep compiler happy... */
  781.      short protmode;
  782. +    int i;
  783. +
  784. +/* if we're about to do an exec tell max_rsize which of the exec'ing
  785. +   process regions will be freed, but don't free them yet so the process
  786. +   can still get an ENOMEM...
  787. +*/
  788. +    if (execproc) {
  789. +        for (i = 0; i < execproc->num_reg; i++) {
  790. +            m = execproc->mem[i];
  791. +            if (m && m->links == 1)
  792. +                m->links = 0xfffe;
  793. +        }
  794. +
  795. +/* if parents mem saved because of a blocking fork that can be restored too
  796. +*/
  797. +        if ((parent = pid2proc(execproc->ppid)) &&
  798. +            parent->wait_q == WAIT_Q && 
  799. +            parent->wait_cond == (long)execproc) {
  800. +            for (i = 0; i < parent->num_reg; i++) {
  801. +                m = parent->mem[i];
  802. +                if (m && (m->mflags & M_FSAVED)) {
  803. +                    m->links = 0xfffe;
  804. +                    savemem = m;
  805. +                    break;
  806. +                }
  807. +            }
  808. +        }
  809. +    }
  810.  
  811.  /* if flags & F_ALTLOAD == 1, then we might decide to load in alternate
  812.     RAM if enough is available. "enough" is: if more alt ram than ST ram,
  813.     load there; otherwise, if more than (minalt+1)*128K alt ram available
  814.     for heap space, load in alt ram ("minalt" is the high byte of flags)
  815.   */
  816. +    if (flags & (F_ALTLOAD|F_SHTEXT)) {
  817. +        minalt = (flags & F_MINALT) >> 28L;
  818. +        minalt = len = (minalt+1)*128*1024L + prgsize + 256;
  819. +        if ((flags & F_MINALT) == F_MINALT)
  820. +            len = 0;
  821. +    }
  822.      if (flags & F_ALTLOAD) {
  823. -        coresize = max_rsize(core);
  824. -        altsize = max_rsize(alt);
  825. -        if (altsize >= coresize)
  826. +        coresize = max_rsize(core, len);
  827. +        altsize = max_rsize(alt, len);
  828. +        if (altsize >= coresize) {
  829.              map = alt;
  830. -        else {
  831. -            len = (flags & F_MINALT) >> 28L;
  832. -            len = (len+1)*128*1024L + prgsize + 256;
  833. -            if (altsize >= len)
  834. +            len = altsize;
  835. +        } else {
  836. +            if (altsize >= minalt) {
  837.                  map = alt;
  838. -            else
  839. +                len = altsize;
  840. +            } else {
  841.                  map = core;
  842. +                len = coresize;
  843. +            }
  844.          }
  845.      }
  846.      else
  847. -        map = core;
  848. +        len = max_rsize((map = core), len);
  849.  
  850. -    len = max_rsize(map);
  851. +    if (savemem)
  852. +        savemem->links = 1;
  853.      if (curproc->maxmem && len > curproc->maxmem) {
  854.          len = curproc->maxmem;
  855.      }
  856.  
  857. -    if (len < prgsize) {
  858. -        /* can't possibly load this file in its eligible regions */
  859. -        DEBUG(("create_base: max_rsize smaller than prgsize"));
  860. -        return 0;
  861. -    }
  862. -
  863.  /* make sure that a little bit of memory is left over */
  864.      if (len > 2*KEEP_MEM) {
  865.          len -= KEEP_MEM;
  866.      }
  867. -
  868. +    if (s && !s->text &&
  869. +        (!(flags & F_ALTLOAD) || map == alt || altsize < fh->ftext ||
  870. +         !(s->text = addr2mem(alloc_region(alt, fh->ftext, PROT_P))))) {
  871. +        if (len > fh->ftext + KERNEL_MEM)
  872. +            len -= fh->ftext + KERNEL_MEM;
  873. +        else
  874. +            len = 0;
  875. +    }
  876. +
  877. +    if (prgsize && len < prgsize + 0x400) {
  878. +        /* can't possibly load this file in its eligible regions */
  879. +        DEBUG(("create_base: max_rsize smaller than prgsize"));
  880. +
  881. +        if (execproc) {
  882. +/* error, undo the above */
  883. +            for (i = 0; i < execproc->num_reg; i++) {
  884. +                m = execproc->mem[i];
  885. +                if (m && m->links == 0xfffe)
  886. +                    m->links = 1;
  887. +            }
  888. +        }
  889. +        if (s && !s->text) {
  890. +            kfree (s);
  891. +        }
  892. +        mint_errno = ENSMEM;
  893. +        return 0;
  894. +    }
  895. +    if (execproc) {
  896. +/* free exec'ing process memory... if the exec returns after this make it
  897. +   _exit (SIGKILL << 8);
  898. +*/
  899. +        *((short *) (execproc->stack + ISTKSIZE + sizeof (void (*)()))) =
  900. +            (SIGKILL << 8);
  901. +        execproc->ctxt[SYSCALL].term_vec = (long)rts;
  902. +        execproc->ctxt[SYSCALL].pc = (long)terminateme;
  903. +        execproc->ctxt[SYSCALL].sr |= 0x2000;
  904. +        execproc->ctxt[SYSCALL].ssp = (long)(execproc->stack + ISTKSIZE);
  905. +
  906. +        if (savemem)
  907. +            fork_restore(parent, savemem);
  908. +        for (i = 0; i < execproc->num_reg; i++) {
  909. +            m = execproc->mem[i];
  910. +            if (m && m->links == 0xfffe) {
  911. +                if (m->mflags & M_SHTEXT_T) {
  912. +                    m->links = 0xffff;
  913. +                } else {
  914. +                    m->links = 0;
  915. +                    free_region(m);
  916. +                }
  917. +                execproc->mem[i] = 0;
  918. +                execproc->addr[i] = 0;
  919. +            }
  920. +        }
  921. +    }
  922.      protmode = (flags & F_PROTMODE) >> F_PROTSHIFT;
  923.  
  924. -    m = addr2mem(alloc_region(map, len, protmode));
  925. +    m = 0;
  926. +    if (s && !s->f) {
  927. +        if (!s->text) {
  928. +            m = addr2mem(alloc_region(map, len + fh->ftext + KERNEL_MEM, protmode));
  929. +            if (!m ||
  930. +                (((len > minalt &&
  931. +                ((flags & F_MINALT) < F_MINALT) &&
  932. +                max_rsize (map, -1) < fh->ftext) ||
  933. +                  !(s->text = addr2mem(alloc_region(map, fh->ftext, PROT_P))) ||
  934. +                  (m->next == s->text &&
  935. +                !(detach_region (curproc, s->text), s->text = 0))) &&
  936. +                 shrink_region(m, fh->ftext))) {
  937. +                if (m)
  938. +                    detach_region(curproc, m);
  939. +                kfree (s);
  940. +                mint_errno = ENSMEM;
  941. +                return 0;
  942. +            }
  943. +            if (!s->text) {
  944. +                s->text = m;
  945. +                if (protmode != PROT_P)
  946. +                    change_prot_status (curproc, m->loc, PROT_P);
  947. +                m = 0;
  948. +            }
  949. +        }
  950. +        s = get_text_seg(f, fh, xp, s, 0);
  951. +        if (!s) {
  952. +            if (m)
  953. +                detach_region(curproc, m);
  954. +            DEBUG(("create_base: unable to load shared text segment"));
  955. +/* mint_errno set in get_text_seg */
  956. +            return 0;
  957. +        }
  958. +    }
  959. +
  960. +    if (!m) {
  961. +        m = addr2mem(alloc_region(map, len, protmode));
  962. +    }
  963.      if (!m) {
  964.          DEBUG(("create_base: alloc_region failed"));
  965. +        mint_errno = ENSMEM;
  966.          return 0;
  967.      }
  968.      b = (BASEPAGE *)(m->loc);
  969. @@ -1062,7 +1329,7 @@
  970.   */
  971.  
  972.  MEMREGION *
  973. -load_region(filename, env, cmdlin, xp, text, fp)
  974. +load_region(filename, env, cmdlin, xp, text, fp, isexec)
  975.      const char *filename;
  976.      MEMREGION *env;
  977.      const char *cmdlin;
  978. @@ -1070,6 +1337,7 @@
  979.      MEMREGION **text;    /* set to point to shared text region,
  980.                     if any */
  981.      long *fp;        /* prgflags for this file */
  982. +    int isexec;        /* this is an exec*() (overlay) */
  983.  {
  984.      FILEPTR *f;
  985.      DEVDRV *dev;
  986. @@ -1077,6 +1345,7 @@
  987.      BASEPAGE *b;
  988.      long size, start;
  989.      FILEHEAD fh;
  990. +    SHTEXT *s;
  991.  
  992.  /* bug: this should be O_DENYW mode, not O_DENYNONE */
  993.  /* we must use O_DENYNONE because of the desktop and because of the
  994. @@ -1105,30 +1374,45 @@
  995.  
  996.      if (fh.flag & F_SHTEXT) {
  997.          TRACE(("loading shared text segment"));
  998. -        shtext = get_text_seg(f, &fh, xp);
  999. -        if (!shtext) {
  1000. +        s = get_text_seg(f, &fh, xp, 0L, isexec);
  1001. +        if (!s) {
  1002.              DEBUG(("load_region: unable to get shared text segment"));
  1003.  /* mint_errno set in get_text_seg */
  1004.              goto failed;
  1005.          }
  1006.          size = fh.fdata + fh.fbss;
  1007. +        shtext = s->text;
  1008.      } else {
  1009.          size = fh.ftext + fh.fdata + fh.fbss;
  1010.          shtext = 0;
  1011. +        s = 0;
  1012.      }
  1013.  
  1014. -    reg = create_base(cmdlin, env, fh.flag, size);
  1015. +    env->links++;
  1016. +    if (s && !shtext) {
  1017. +        reg = create_base(cmdlin, env, fh.flag, size,
  1018. +            isexec ? curproc : 0L, s, f, &fh, xp);
  1019. +        shtext = s->text;
  1020. +    } else {
  1021. +        if (shtext)
  1022. +            shtext->links++;
  1023. +        reg = create_base(cmdlin, env, fh.flag, size,
  1024. +            isexec ? curproc : 0L, 0L, 0L, 0L, 0L);
  1025. +        if (shtext)
  1026. +            shtext->links--;
  1027. +    }
  1028. +    env->links--;
  1029.      if (reg && size+1024L > reg->len) {
  1030.          DEBUG(("load_region: insufficient memory to load"));
  1031.          detach_region(curproc, reg);
  1032.          reg = 0;
  1033. +        mint_errno = ENSMEM;
  1034.      }
  1035.  
  1036.      if (reg == 0) {
  1037.          if (shtext) {
  1038.              detach_region(curproc, shtext);
  1039.          }
  1040. -        mint_errno = ENSMEM;
  1041.          goto failed;
  1042.      }
  1043.  
  1044. @@ -1294,58 +1578,70 @@
  1045.   * process
  1046.   */
  1047.  
  1048. -MEMREGION *
  1049. -get_text_seg(f, fh, xp)
  1050. +SHTEXT *
  1051. +get_text_seg(f, fh, xp, s, noalloc)
  1052.      FILEPTR *f;
  1053.      FILEHEAD *fh;
  1054.      XATTR *xp;
  1055. -{
  1056.      SHTEXT *s;
  1057. +    int noalloc;
  1058. +{
  1059.      MEMREGION *m;
  1060.      long r;
  1061.      BASEPAGE b;
  1062.  
  1063. -    s = text_reg;
  1064. +    if (s) {
  1065. +        m = s->text;
  1066. +    } else {
  1067. +        s = text_reg;
  1068.  
  1069. -    while(s) {
  1070. -        if (s->f && samefile(&f->fc, &s->f->fc) &&
  1071. -            xp->mtime == s->mtime &&
  1072. -            xp->mdate == s->mdate)
  1073. -        {
  1074. -            m = s->text;
  1075. +        while(s) {
  1076. +            if (s->f && samefile(&f->fc, &s->f->fc) &&
  1077. +                xp->mtime == s->mtime &&
  1078. +                xp->mdate == s->mdate)
  1079. +            {
  1080. +                m = s->text;
  1081.  /* Kludge for unattached shared region */
  1082. -            if (m->links == 0xffff)
  1083. -                m->links = 0;
  1084. +                if (m->links == 0xffff)
  1085. +                    m->links = 0;
  1086.  
  1087. -            if (attach_region(curproc, m)) {
  1088. +                if (attach_region(curproc, m)) {
  1089.  TRACE(("re-using shared text region %lx", m));
  1090. -                return m;
  1091. -            }
  1092. -            else {
  1093. -                mint_errno = ENSMEM;
  1094. -                return 0;
  1095. +                    return s;
  1096. +                }
  1097. +                else {
  1098. +                    mint_errno = ENSMEM;
  1099. +                    return 0;
  1100. +                }
  1101.              }
  1102. +            s = s->next;
  1103.          }
  1104. -        s = s->next;
  1105. -    }
  1106.  
  1107.  /* hmmm, not found; OK, we'll have to create a new text region */
  1108.  
  1109. -    s = kmalloc(SIZEOF(SHTEXT));
  1110. -    if (!s) {
  1111. -        mint_errno = ENSMEM;
  1112. -        return 0;
  1113. +        s = kmalloc(SIZEOF(SHTEXT));
  1114. +        if (!s) {
  1115. +            mint_errno = ENSMEM;
  1116. +            return 0;
  1117. +        }
  1118. +        if (noalloc) {
  1119. +            s->f = 0;
  1120. +            s->text = 0;
  1121. +            return s;
  1122. +        }
  1123. +        m = 0;
  1124.      }
  1125. -    m = 0;
  1126. +    if (!m) {
  1127.  /* actually, I can't see why loading in TT RAM is ever undesireable,
  1128.   * since shared text programs should be very clean (and since only
  1129.   * the text segment is going in there). But better safe than sorry.
  1130.   */
  1131. -    if (fh->flag & F_ALTLOAD) {
  1132. -        m = addr2mem(alloc_region(alt, fh->ftext, PROT_P));
  1133. +        if (fh->flag & F_ALTLOAD) {
  1134. +            m = addr2mem(alloc_region(alt, fh->ftext, PROT_P));
  1135. +        }
  1136. +        if (!m)
  1137. +            m = addr2mem(alloc_region(core, fh->ftext, PROT_P));
  1138.      }
  1139. -    if (!m)
  1140. -        m = addr2mem(alloc_region(core, fh->ftext, PROT_P));
  1141.  
  1142.      if (!m) {
  1143.          kfree(s);
  1144. @@ -1375,6 +1671,11 @@
  1145.  
  1146.  /* region has valid shared text data */
  1147.      m->mflags |= M_SHTEXT;
  1148. +#if 1
  1149. +    if (xp->mode & 01000)
  1150. +#endif
  1151. +/* make it sticky (this should depend on the files mode!?) */
  1152. +    m->mflags |= M_SHTEXT_T;
  1153.  
  1154.  /*
  1155.   * KLUDGE: to make sure we always have up to date shared text
  1156. @@ -1395,7 +1696,25 @@
  1157.      s->mdate = xp->mdate;
  1158.      text_reg = s;
  1159.  TRACE(("shared text region %lx created", m));
  1160. -    return m;
  1161. +    return s;
  1162. +}
  1163. +
  1164. +/*
  1165. + * function to just check for existence of a shared text region
  1166. + * corresponding to file "f"
  1167. + */
  1168. +
  1169. +MEMREGION *
  1170. +find_text_seg(f)
  1171. +    FILEPTR *f;
  1172. +{
  1173. +    SHTEXT *s;
  1174. +
  1175. +    for (s = text_reg; s; s = s->next) {
  1176. +        if (s->f && samefile(&f->fc, &s->f->fc))
  1177. +            return s->text;
  1178. +    }
  1179. +    return 0;
  1180.  }
  1181.  
  1182.  /*
  1183. Index: mem.h
  1184. @@ -25,6 +25,8 @@
  1185.  #define M_MAP        0x0f    /* and with this to pick out map */
  1186.  
  1187.  #define M_SHTEXT    0x10    /* region is a shared text region */
  1188. +#define M_SHTEXT_T    0x20    /* `sticky bit' for shared text regions */
  1189. +#define M_FSAVED    0x40    /* region is saved memory of a forked process */
  1190.  #define M_KEEP        0x0100    /* don't free on process termination */
  1191.  
  1192.  /* dummy type for virtual addresses */
  1193. Index: proto.h
  1194. @@ -154,6 +154,7 @@
  1195.  long ARGS_ON_STACK p_waitpid P_((int pid, int nohang, long *rusage));
  1196.  long ARGS_ON_STACK p_wait3 P_((int nohang, long *rusage));
  1197.  long ARGS_ON_STACK p_wait P_((void));
  1198. +void ARGS_ON_STACK fork_restore P_((PROC *p, MEMREGION *savemem));
  1199.  long ARGS_ON_STACK p_vfork P_((void));
  1200.  long ARGS_ON_STACK p_fork P_((void));
  1201.  
  1202. @@ -217,14 +218,16 @@
  1203.  MEMREGION *get_region P_((MMAP map, ulong size, int mode));
  1204.  void free_region P_((MEMREGION *reg));
  1205.  long shrink_region P_((MEMREGION *reg, ulong newsize));
  1206. -long max_rsize P_((MMAP map));
  1207. +long max_rsize P_((MMAP map, long needed));
  1208.  long tot_rsize P_((MMAP map, int flag));
  1209.  virtaddr alloc_region P_((MMAP map, ulong size, int mode));
  1210.  MEMREGION *create_env P_((const char *env, ulong flags));
  1211. -MEMREGION *create_base P_((const char *cmd, MEMREGION *env, ulong flags, ulong prgsize));
  1212. +MEMREGION *create_base P_((const char *cmd, MEMREGION *env, ulong flags, ulong prgsize,
  1213. +            PROC *execproc, SHTEXT *s, FILEPTR *f, FILEHEAD *fh, XATTR *xp));
  1214.  MEMREGION *load_region P_((const char *name, MEMREGION *env, const char *cmdlin, XATTR *x,
  1215. -            MEMREGION **text, long *fp));
  1216. -MEMREGION *get_text_seg P_((FILEPTR *f, FILEHEAD *fh, XATTR *xp));
  1217. +            MEMREGION **text, long *fp, int isexec));
  1218. +SHTEXT *get_text_seg P_((FILEPTR *f, FILEHEAD *fh, XATTR *xp, SHTEXT *s, int noalloc));
  1219. +MEMREGION *find_text_seg P_((FILEPTR *f));
  1220.  long load_and_reloc P_((FILEPTR *f, FILEHEAD *fh, char *where, long start,
  1221.              long nbytes, BASEPAGE *base));
  1222.  void rts P_((void));
  1223. -- 
  1224. J"urgen Lock / nox@jelal.north.de / UUCP: ..!uunet!unido!uniol!jelal!nox
  1225.                                 ...ohne Gewehr
  1226. PGP public key fingerprint =  8A 18 58 54 03 7B FC 12  1F 8B 63 C7 19 27 CF DA 
  1227.